package org.kjtw.process;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.FloatControl;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
public class AudioPlayer implements Runnable{
ExecutorService soundPool = Executors.newFixedThreadPool(1);
private byte[] audio;
private AudioInputStream audioStream = null;
private AudioFormat audioFormat = null;
private SourceDataLine sourceLine = null;
private volatile boolean stopFlag = false;
private volatile boolean pauseFlag = false;
private volatile boolean isPlayingFlag = false;
private volatile float volume_dB = 0.0f;
public AudioPlayer(byte[] bytes)
{
this.audio = bytes;
}
/**
* @param filename the name of the file that is going to be played
* @throws IOException
* @throws UnsupportedAudioFileException
* @throws FileNotFoundException
* @throws LineUnavailableException
*/
public void playSound() throws FileNotFoundException, UnsupportedAudioFileException, IOException, LineUnavailableException
{
if (audio != null)
{
isPlayingFlag = true;
InputStream snd = new ByteArrayInputStream(audio);
audioStream = AudioSystem.getAudioInputStream(snd);
audioFormat = audioStream.getFormat();
final byte[] data = new byte[4096];
try{
SourceDataLine res = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
res = (SourceDataLine) AudioSystem.getLine(info);
res.open(audioFormat);
sourceLine = res;
// Start
onPlay();
sourceLine.start();
int nBytesRead = 0;
while ((nBytesRead != -1) && (!stopFlag))
{
if(!pauseFlag)
{
isPlayingFlag = true;
nBytesRead = audioStream.read(data, 0, data.length);
if (nBytesRead != -1)
{
if (sourceLine.isControlSupported(FloatControl.Type.MASTER_GAIN))
{
((FloatControl) sourceLine.getControl(FloatControl.Type.MASTER_GAIN)).setValue(volume_dB);
}
sourceLine.write(data, 0, nBytesRead);
}
}
else
{
isPlayingFlag = false;
}
}
// Stop
sourceLine.drain();
sourceLine.stop();
sourceLine.close();
audioStream.close();
}catch(LineUnavailableException e){
e.printStackTrace();
}
isPlayingFlag = false;
onStop();
}
}
@Override
public void run()
{
stopFlag = false;
pauseFlag = false;
Runnable soundPlay = new Runnable() {
@Override
public void run() {
try {
playSound();
} catch (UnsupportedAudioFileException ex) {
Logger.getLogger(AudioPlayer.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(AudioPlayer.class.getName()).log(Level.SEVERE, null, ex);
} catch (LineUnavailableException ex) {
Logger.getLogger(AudioPlayer.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
soundPool.execute(soundPlay);
// try {
// playSound();
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (UnsupportedAudioFileException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// } catch (LineUnavailableException e) {
// e.printStackTrace();
// }
}
public void play()
{
run();
}
public void onPlay(){}
public void pause()
{
pauseFlag = true;
onPause();
}
public void onPause(){}
public void resume()
{
pauseFlag = false;
onResume();
}
public void onResume(){}
public void stop()
{
stopFlag = true;
}
public void onStop(){}
public boolean isPlaying()
{
return isPlayingFlag;
}
public boolean isPaused()
{
return pauseFlag;
}
public void setVolume(Float volume)
{
volume = volume==null ? 1.0F : volume;
volume = volume<=0.0F ? 0.0001F : volume;
setVolumeInDecibels((float)( 20.0*(Math.log(volume)/Math.log(10.0)) ));
}
public void setVolumeInDecibels(Float decibels)
{
decibels = decibels==null ? 0.0F : decibels;
this.volume_dB = decibels;
}
}